package com.dog.basics.common.fluorite.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.fluorite.request.RequestData;
import com.dog.basics.common.fluorite.request.RequestLiveBroadcastVo;
import com.dog.basics.common.properties.FluoriteProperties;
import com.dog.basics.common.util.R;
import com.dog.basics.common.util.RedisUtil;
import com.dog.basics.common.util.ToolUtil;

import java.util.Date;
import java.util.Map;

/**
 * @description: 萤石业务执行
 * @author: He
 * @date: Created in 2020/7/4 16:21
 * @version: 1.0
 * @modified By:
 */
public class FluoriteUtil {

    /**
     * 萤石Url = 获取token信息
     */
    private String tokenUrl = "https://open.ys7.com/api/lapp/token/get";
    /**
     * 萤石Url = 设备抓拍图片
     */
    private String captureUrl = "https://open.ys7.com/api/lapp/device/capture";
    /**
     * 萤石Url = 关闭设备视频加密
     */
    private String encryptOffUrl = "https://open.ys7.com/api/lapp/device/encrypt/off";
    /**
     * 萤石Url = 开启设备视频加密
     */
    private String encryptOnUrl = "https://open.ys7.com/api/lapp/device/encrypt/on";

    /**
     * 获取指定有效期的直播地址
     */
    private String liveBroadcastUrl = "https://open.ys7.com/api/lapp/live/address/limited";

    /**
     * 添加设备到账号下
     */
    private String addDeviceUrl = "https://open.ys7.com/api/lapp/device/add";

    /**
     * 删除设备
     */
    private String delDeviceUrl = "https://open.ys7.com/api/lapp/device/delete";

    /**
     * 修改设备名称
     */
    private String editDeviceUrl = "https://open.ys7.com/api/lapp/device/name/update";

    /**
     * 萤石配置信息
     */
    private FluoriteProperties fluoriteProperties;

    /**
     * 构造方法
     *
     * @param fluoriteProperties
     */
    public FluoriteUtil(FluoriteProperties fluoriteProperties) {
        this.fluoriteProperties = fluoriteProperties;
    }


    /**
     * @功能描述: 获取萤石 Token
     * @author He
     * @date 2020/7/4
     */
    public String getFluoriteTokenStr() {
        // 查询 Redis 中token
        Object token = RedisUtil.get(StrUtil.format("{}{}", CommonConstants.YS_TOKEN, fluoriteProperties.getAppKey()));
        // 判断是有此token
        if (ObjectUtils.isNotNull(token)) {
            return StrUtil.toString(token);
        }
        // 查询 GetToken
        R<String> fluoriteToken = getFluoriteToken();
        if (!Validator.equal(fluoriteToken.getCode(), 0)) {
            return StrUtil.str("NULL.A");
        }
        return fluoriteToken.getData();
    }

    /**
     * 内部查询getToken信息
     *
     * @return
     */
    private R<String> getFluoriteToken() {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("appKey", fluoriteProperties.getAppKey());
        formDto.put("appSecret", fluoriteProperties.getAppSecret());
        // 头信息，多个头信息多次调用此方法即可
        String requestPost = HttpUtil.post(tokenUrl, formDto);
        //{"data":{"accessToken":"at.blnhiwow3as4u50pas473wut3qkybozo-3gmo9hxd71-1dzs7kl-ywtgsrlac","expireTime":1594457216525},"code":"200","msg":"操作成功!"}
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        if (!Validator.equal(requestData.getCode(), 200)) {
            return R.failed(requestData.getMsg());
        }
        String accessToken = StrUtil.toString(requestData.getData().get("accessToken"));
        // 判断是否多长时间
        Object expireTime = requestData.getData().get("expireTime");
        Date expireTimeDate = DateUtil.date(Long.valueOf(StrUtil.toString(expireTime)));
        Long dateBetweenMs = DateUtil.betweenMs(expireTimeDate, DateUtil.date());
        // 放入Redis中
        RedisUtil.set(StrUtil.format("{}{}", CommonConstants.YS_TOKEN, fluoriteProperties.getAppKey()), accessToken, ToolUtil.dateSecond(dateBetweenMs));
        return R.ok(accessToken);
    }

    /**
     * @功能描述: 获取指定有效期的直播地址
     * @author He
     * @date 2020/7/8
     */
    @SuppressWarnings("all")
    public R<RequestLiveBroadcastVo> getLiveBroadcast(String deviceSerial, Integer channelNo) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        formDto.put("channelNo", channelNo);
        String requestPost = HttpUtil.post(liveBroadcastUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        //{"data":{"picUrl":"https://fastgw-ali.ys7.com/1/capture/2020/7/4/1t18qgh3y2o35slk5vov0jif4.jpg?Expires=1593939555&OSSAccessKeyId=LTAIzI38nEHqg64n&Signature=hJfHVmaSBMdtemAfz2dWHOiFv80%3D&bucket=ezviz-fastdfs-gateway"},"code":"200","msg":"操作成功!"}
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            return R.failed(requestData.getMsg());
        }
        RequestLiveBroadcastVo liveBroadcastVo = BeanUtil.toBean(requestData.getData(), RequestLiveBroadcastVo.class);
        return R.ok(liveBroadcastVo);
    }


    /**
     * @功能描述: 萤石抓取摄像头图片
     * @author He
     * @date 2020/7/8
     */
    @SuppressWarnings("all")
    public R<String> getFluoriteCapturePictures(String deviceSerial, Integer channelNo) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        formDto.put("channelNo", channelNo);
        String requestPost = HttpUtil.post(captureUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        //{"data":{"picUrl":"https://fastgw-ali.ys7.com/1/capture/2020/7/4/1t18qgh3y2o35slk5vov0jif4.jpg?Expires=1593939555&OSSAccessKeyId=LTAIzI38nEHqg64n&Signature=hJfHVmaSBMdtemAfz2dWHOiFv80%3D&bucket=ezviz-fastdfs-gateway"},"code":"200","msg":"操作成功!"}
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            return R.failed(requestData.getMsg());
        }
        return R.ok(StrUtil.toString(requestData.getData().get("picUrl")));
    }

    /**
     * @param deviceSerial 设备序列号
     * @param validateCode 设备验证码
     * @功能描述: 添加设备到账号下
     * @author wph
     * @date 2020/89/15
     */
    @SuppressWarnings("all")
    public Boolean addDeviceUrl(String deviceSerial, String validateCode) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        formDto.put("validateCode", validateCode);
        String requestPost = HttpUtil.post(addDeviceUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            if(Validator.equal(requestData.getCode(), 10005)){
                Validator.validateTrue(Boolean.FALSE, "账号被冻结");
                return Boolean.FALSE;
            }
            if(Validator.equal(requestData.getCode(), 20014)){
                Validator.validateTrue(Boolean.FALSE, "设备序列号不合法");
                return Boolean.FALSE;
            }
            Validator.validateTrue(Boolean.FALSE, requestData.getMsg());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * @param deviceSerial 设备序列号
     * @param deviceName   设备名字 最多50
     * @功能描述: 添加设备到账号下
     * @author wph
     * @date 2020/89/15
     */
    @SuppressWarnings("all")
    public Boolean editDeviceUrl(String deviceSerial, String deviceName) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        formDto.put("deviceName", deviceName);
        String requestPost = HttpUtil.post(editDeviceUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            if(Validator.equal(requestData.getCode(), 10005)){
                Validator.validateTrue(Boolean.FALSE, "账号被冻结");
                return Boolean.FALSE;
            }
            if(Validator.equal(requestData.getCode(), 20014)){
                Validator.validateTrue(Boolean.FALSE, "设备序列号不合法");
                return Boolean.FALSE;
            }
            Validator.validateTrue(Boolean.FALSE, requestData.getMsg());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * @param deviceSerial 设备序列号
     * @功能描述: 删除设备
     * @author wph
     * @date 2020/89/15
     */
    @SuppressWarnings("all")
    public Boolean delDeviceUrl(String deviceSerial) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(2);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        String requestPost = HttpUtil.post(delDeviceUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            if(Validator.equal(requestData.getCode(), 10005)){
                Validator.validateTrue(Boolean.FALSE, "账号被冻结");
                return Boolean.FALSE;
            }
            if(Validator.equal(requestData.getCode(), 20014)){
                Validator.validateTrue(Boolean.FALSE, "设备序列号不合法");
                return Boolean.FALSE;
            }
            Validator.validateTrue(Boolean.FALSE, requestData.getMsg());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * @功能描述: 开启设备视频加密
     * @author He
     * @date 2020/7/4
     */
    @SuppressWarnings("all")
    public R<Boolean> getFluoriteEncryptOn(String deviceSerial) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(2);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        String requestPost = HttpUtil.post(encryptOnUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        // 判断是否 200 成功 成功则数据信息
        if (!Validator.equal(requestData.getCode(), 200)) {
            return R.failed(requestData.getMsg());
        }
        return R.ok();
    }

    /**
     * @功能描述: 关闭设备视频加密
     * @author He
     * @date 2020/7/4
     */
    @SuppressWarnings("all")
    public Boolean getFluoriteEncryptOff(String deviceSerial, String validateCode) {
        // Map 参数信息声明
        Map<String, Object> formDto = CollUtil.newHashMap(3);
        formDto.put("accessToken", getFluoriteTokenStr());
        formDto.put("deviceSerial", deviceSerial);
        formDto.put("validateCode", validateCode);
        String requestPost = HttpUtil.post(encryptOffUrl, formDto);
        // 结果通知 转换
        RequestData requestData = JSONUtil.toBean(requestPost, RequestData.class);
        // 判断是否 200 成功 成功则数据信息
        if (Validator.equal(requestData.getCode(), 200)||Validator.equal(requestData.getCode(), 60016)) {

            return Boolean.TRUE;
        }else{
            Validator.validateTrue(Boolean.FALSE, requestData.getMsg());
            return Boolean.FALSE;
        }

    }

}